home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_unix / j109lxa4.tar / unixasy.c < prev    next >
C/C++ Source or Header  |  1994-06-04  |  16KB  |  780 lines

  1. /*
  2.  * File stolen from WAMPES 921229, modified for compatibility with JNOS and my
  3.  * tastes, and left to sink or swim.  Blub!  ++bsa
  4.  *
  5.  * The actual structure is much closer to that of JNOS than to WAMPES.  The
  6.  * reason is that WAMPES uses these weirdball I/O hooks... We will use the
  7.  * "classic" interface, modified by the use of register_fd().  (Actually, the
  8.  * weirdball I/O hooks are just WAMPES's version of register_fd().  The API
  9.  * for WAMPES is a heck of a lot hairier, though.)
  10.  */
  11.  
  12. #include <sys/types.h>
  13.  
  14. #include <fcntl.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <termios.h>
  18. #include <sys/time.h>
  19. #include <errno.h>
  20.  
  21. #include "global.h"
  22. #include "mbuf.h"
  23. #include "proc.h"
  24. #include "iface.h"
  25. #include "asy.h"
  26. #include "timer.h"
  27. #include "unixasy.h"
  28. #include "hardware.h"
  29. #include "devparam.h"
  30. #include "commands.h"
  31. #include "cmdparse.h"
  32.  
  33. extern int chmod __ARGS((const char *, unsigned));
  34.  
  35. static int find_speed __ARGS((long speed));
  36. static void pasy __ARGS((struct asy *asyp));
  37. static void asy_tx __ARGS((int, void *, void *));
  38. static void asy_input __ARGS((int, void *, void *));
  39.  
  40. struct asy Asy[ASY_MAX];
  41.  
  42. /*---------------------------------------------------------------------------*/
  43.  
  44. static int dorxqueue __ARGS((int argc, char **argv, void *p));
  45. static int dotxqueue __ARGS((int argc, char **argv, void *p));
  46. static int dobufsize __ARGS((int argc, char **argv, void *p));
  47. static int doasy2stat __ARGS((int argc, char **argv, void *p));
  48.  
  49. static struct cmds AsyPcmds[] =
  50. {
  51.     "rxqueue",    dorxqueue,    0, 0, NULLCHAR,
  52.     "txqueue",    dotxqueue,    0, 0, NULLCHAR,
  53.     "bufsize",    dobufsize,    0, 0, NULLCHAR,
  54.     "status",    doasy2stat,    0, 0, NULLCHAR,
  55.     0,
  56. };
  57.  
  58. /*---------------------------------------------------------------------------*/
  59.  
  60. static struct {
  61.     long speed;
  62.     speed_t flags;
  63. } speed_table[] = {
  64. #ifdef B50
  65.     50, B50,
  66. #endif
  67. #ifdef B75
  68.     75, B75,
  69. #endif
  70. #ifdef B110
  71.     110, B110,
  72. #endif
  73. #ifdef B134
  74.     134, B134,
  75. #endif
  76. #ifdef B150
  77.     150, B150,
  78. #endif
  79. #ifdef B200
  80.     200, B200,
  81. #endif
  82. #ifdef B300
  83.     300, B300,
  84. #endif
  85. #ifdef B600
  86.     600, B600,
  87. #endif
  88. #ifdef B900
  89.     900, B900,
  90. #endif
  91. #ifdef B1200
  92.     1200, B1200,
  93. #endif
  94. #ifdef B1800
  95.     1800, B1800,
  96. #endif
  97. #ifdef B2400
  98.     2400, B2400,
  99. #endif
  100. #ifdef B3600
  101.     3600, B3600,
  102. #endif
  103. #ifdef B4800
  104.     4800, B4800,
  105. #endif
  106. #ifdef B7200
  107.     7200, B7200,
  108. #endif
  109. #ifdef B9600
  110.     9600, B9600,
  111. #endif
  112. #ifdef B19200
  113.     19200, B19200,
  114. #endif
  115. #ifdef B38400
  116.     38400, B38400,
  117. #endif
  118. #ifdef B57600
  119.     57600, B57600,
  120. #endif
  121. #ifdef B115200
  122.     115200, B115200,
  123. #endif
  124. #ifdef B230400
  125.     230400, B230400,
  126. #endif
  127. #ifdef B460800
  128.     460800, B460800,
  129. #endif
  130.     -1, 0
  131. };
  132.  
  133. /*---------------------------------------------------------------------------*/
  134.  
  135. static int
  136. find_speed(speed)
  137. long speed;
  138. {
  139.     int i;
  140.  
  141.     i = 0;
  142.     while (speed_table[i].speed < speed && speed_table[i+1].speed > 0)
  143.         i++;
  144.     return i;
  145. }
  146.  
  147. /*---------------------------------------------------------------------------*/
  148.  
  149. /* Initialize asynch port "dev" */
  150. int
  151. asy_init(dev,ifp,arg1,arg2,bufsize,trigchar,monitor,speed,force,triglevel)
  152.     int dev;
  153.     struct iface *ifp;
  154.     char *arg1,*arg2;       /* Attach args for address and vector */
  155.     int16 bufsize;
  156.     int trigchar;
  157.     char monitor;
  158.     long speed;
  159.     int force;
  160.     int triglevel;
  161. {
  162.     register struct asy *ap;
  163.     char filename[80];
  164.     char *ifn;
  165.     int sp, fd;
  166.     struct termios termios;
  167.  
  168.     ap = &Asy[dev];
  169.  
  170.     /* UUCP locking with ASCII pid */
  171.     strcpy(ap->uulock, "/usr/spool/uucp/LCK..");
  172.     strcat(ap->uulock, arg1);
  173.     for (;;)
  174.     {
  175.     if ((fd = open(ap->uulock, O_WRONLY|O_CREAT|O_EXCL, 0644)) != -1 ||
  176.         errno != EEXIST)
  177.         break;
  178.     /* read pid, unlink and retry if proc no longer exists */
  179.     if ((fd = open(ap->uulock, O_RDONLY)) == -1)
  180.         continue;    /* timing is everything */
  181.     filename[read(fd, filename, 10)] = '\0';
  182.     close(fd);
  183.     sscanf(filename, "%d", &fd);
  184.     if (kill(fd, 0) == -1 && errno == ESRCH)
  185.     {
  186.         tprintf("Removing stale lockfile for %s\n", arg1);
  187.         unlink(ap->uulock);
  188.         continue;
  189.     }
  190.     tprintf("/dev/%s is locked\n", arg1);
  191.     ap->uulock[0] = '\0'; /* so it won't clobber existing lock */
  192.     goto Fail;
  193.     }
  194.     if (fd == -1)
  195.     {
  196.     tprintf("Can't lock /dev/%s: %s\n", arg1, strerror(errno));
  197.     ap->uulock[0] = '\0';
  198.     goto Fail;
  199.     }
  200.     chmod(ap->uulock, 0644); /* beware of overly restrictive umask */
  201.     sprintf(filename, "%10d\n", getpid());
  202.     write(fd, filename, 11);
  203.     close(fd);
  204.  
  205.     strcpy(filename, "/dev/");
  206.     strcat(filename, arg1);
  207.     if ((fd = open(filename, O_RDWR|O_NONBLOCK|O_NOCTTY, 0644)) == -1)
  208.     {
  209.     tprintf("Can't open port: %s\n", strerror(errno));
  210.     goto Fail;
  211.     }
  212.     ap->flags = 0;
  213.     ap->iface = ifp;
  214.     sp = find_speed(speed);
  215.     ap->speed = speed_table[sp].speed;
  216.     memset((char *) &termios, 0, sizeof(termios));
  217.     termios.c_iflag = IGNBRK|IGNPAR;
  218.     termios.c_cflag = CS8|CREAD|CLOCAL|speed_table[sp].flags;
  219.     termios.c_cc[VTIME] = 2;
  220.     if ((ap->pktsize = triglevel & 255))
  221.     termios.c_cc[VMIN] = triglevel & 255;
  222.     if (cfsetispeed(&termios, speed_table[sp].flags) == -1)
  223.     {
  224.     tprintf("Can't set speed: %s\n", strerror(errno));
  225.     goto Fail;
  226.     }
  227.     if (cfsetospeed(&termios, speed_table[sp].flags) == -1)
  228.     {
  229.     tprintf("Can't set speed: %s\n", strerror(errno));
  230.     goto Fail;
  231.     }
  232.     if (tcsetattr(fd, TCSANOW, &termios) == -1)
  233.     {
  234.     tprintf("Can't configure port: %s\n", strerror(errno));
  235.     goto Fail;
  236.     }
  237.     /* security: port won't work until re-opened */
  238.     if ((ap->fd = open(filename, O_RDWR|O_NONBLOCK|O_NOCTTY, 0644)) == -1)
  239.     {
  240.     tprintf("Can't reopen port: %s\n", strerror(errno));
  241.     goto Fail;
  242.     }
  243.     close(fd);
  244.  
  245.     /* new asy parameters, defaulted for now */
  246.     ap->rxq = 1;        /* disable queueing */
  247.     ap->txq = 1;
  248.     ap->rxbuf = bufsize;
  249.  
  250.     /* clear statistics */
  251.     ap->rxints = 0;
  252.     ap->txints = 0;
  253.     ap->rxchar = 0;
  254.     ap->txchar = 0;
  255.     ap->rxput = 0;
  256.     ap->rxovq = 0;
  257.     ap->rxblock = 0;
  258.     ap->txget = 0;
  259.     ap->txovq = 0;
  260.     ap->txblock = 0;
  261.  
  262.     ifp->txproc = newproc(ifn = if_name(ifp," tx"),
  263.               256, asy_tx, dev, ifp, NULL, 0);
  264.     free(ifn);
  265.     ap->rxproc = newproc(ifn = if_name(ifp, " hw"),
  266.              256, asy_input, dev, ifp, NULL, 0);
  267.     free(ifn);
  268.  
  269.     register_io(ap->fd, &ap->fd);
  270.  
  271.     return 0;
  272.  
  273. Fail:
  274.     rflush();        /* make sure the message gets out */
  275.     if (fd != -1)
  276.     close(fd);
  277.     /* Unlock port */
  278.     if (ap->uulock[0])
  279.     unlink(ap->uulock);
  280.     ap->uulock[0] = '\0';
  281.     ap->iface = NULLIF;
  282.     return -1;
  283. }
  284.  
  285. /*---------------------------------------------------------------------------*/
  286.  
  287. int
  288. asy_stop(ifp)
  289. struct iface *ifp;
  290. {
  291.     register struct asy *ap;
  292.  
  293.     ap = &Asy[ifp->dev];
  294.  
  295.     if(ap->iface == NULLIF)
  296.         return -1;      /* Not allocated */
  297.  
  298.     unregister_io(ap->fd);
  299.  
  300.     if (ifp->txproc)
  301.         killproc(ifp->txproc);
  302.     ifp->txproc = 0;
  303.  
  304.     if (ap->rxproc)
  305.         killproc(ap->rxproc);
  306.     ap->rxproc = 0;
  307.  
  308.     ap->iface = NULLIF;
  309.  
  310.     free_q(&ap->sndq);
  311.     close(ap->fd);
  312.  
  313.     free_q(&ap->rcvq);
  314.  
  315.     if (ap->uulock[0])
  316.         unlink(ap->uulock);
  317.     ap->uulock[0] = '\0';
  318.  
  319.     return 0;
  320. }
  321.  
  322. void
  323. detach_all_asy()
  324. {
  325.     register struct asy *ap;
  326.  
  327.     for (ap = Asy; ap != Asy + ASY_MAX; ap++)
  328.     {
  329.     if(ap->iface == NULLIF)
  330.         break;
  331.     unregister_io(ap->fd);
  332.     if (ap->iface->txproc)
  333.         killproc(ap->iface->txproc);
  334.     ap->iface->txproc = 0;
  335.     if (ap->rxproc)
  336.         killproc(ap->rxproc);
  337.     ap->rxproc = 0;
  338.     ap->iface = NULLIF;
  339.     free_q(&ap->sndq);
  340.     free_q(&ap->rcvq);
  341.     close(ap->fd);
  342.     if (ap->uulock[0])
  343.         unlink(ap->uulock);
  344.     ap->uulock[0] = '\0';
  345.     }
  346. }
  347.  
  348.  
  349. /*---------------------------------------------------------------------------*/
  350.  
  351. /* Set asynch line speed */
  352. int
  353. asy_speed(dev, bps)
  354.     int dev;
  355.     long bps;
  356. {
  357.     struct asy *asyp;
  358.     int sp;
  359.     struct termios termios;
  360.  
  361.     if(bps <= 0 || dev >= ASY_MAX)
  362.     return -1;
  363.     asyp = &Asy[dev];
  364.     if(asyp->iface == NULLIF)
  365.     return -1;
  366.     if(bps == 0)
  367.     return -1;
  368.     sp = find_speed(bps);
  369.     if (tcgetattr(asyp->fd, &termios))
  370.     return -1;
  371.     if (cfsetispeed(&termios, speed_table[sp].flags))
  372.     return -1;
  373.     if (cfsetospeed(&termios, speed_table[sp].flags))
  374.     return -1;
  375.     termios.c_cflag &= ~CBAUD;
  376.     termios.c_cflag |= speed_table[sp].flags;
  377.     if (tcsetattr(asyp->fd, TCSANOW, &termios))
  378.     return -1;
  379.     asyp->speed = speed_table[sp].speed;
  380.     return 0;
  381. }
  382.  
  383. /* Set termios VMIN (packet size) */
  384. int
  385. asy_vmin(dev, pktsize)
  386.     int dev;
  387.     long pktsize;
  388. {
  389.     struct termios termios;
  390.     struct asy *asyp;
  391.  
  392.     if (pktsize < 0 || pktsize > 255 || dev >= ASY_MAX)
  393.     return -1;
  394.     if ((asyp = &Asy[dev])->iface == NULLIF)
  395.     return -1;
  396.     if (tcgetattr(asyp->fd, &termios))
  397.     return -1;
  398.     termios.c_cc[VMIN] = asyp->pktsize = pktsize & 255;
  399.     if (tcsetattr(asyp->fd, TCSANOW, &termios))
  400.     return -1;
  401.     return 0;
  402. }
  403.  
  404. /* Set or clear RTS/CTS flow control */
  405. int
  406. asy_rts(dev, onoff)
  407.     int dev;
  408.     unsigned long onoff;
  409. {
  410.     struct termios termios;
  411.     struct asy *asyp;
  412.  
  413.     if ((asyp = &Asy[dev])->iface == NULLIF)
  414.     return -1;
  415.     if (tcgetattr(asyp->fd, &termios))
  416.     return -1;
  417.     /*
  418.      * note sense is reversed as per DOS version, except that we default to
  419.      * RTS/CTS being *off* for compatibility with earlier ALPHA versions
  420.      */
  421.     if (onoff)
  422.     {
  423.     asyp->flags &= ~ASY_RTSCTS;
  424.     termios.c_cflag &= ~CRTSCTS;
  425.     }
  426.     else
  427.     {
  428.     asyp->flags |= ASY_RTSCTS;
  429.     termios.c_cflag |= CRTSCTS;
  430.     }
  431.     if (tcsetattr(asyp->fd, TCSANOW, &termios))
  432.     return -1;
  433.     return 0;
  434. }
  435.  
  436. /*---------------------------------------------------------------------------*/
  437.  
  438. /* Asynchronous line I/O control */
  439. int32
  440. asy_ioctl(ifp, cmd, set, val)
  441. struct iface *ifp;
  442. int cmd;
  443. int set;
  444. int32 val;
  445. {
  446.     struct asy *ap = &Asy[ifp->dev];
  447.  
  448.     switch(cmd){
  449.     case PARAM_SPEED:
  450.     if (set)
  451.         asy_speed(ifp->dev, val);
  452.     return ap->speed;
  453.     case PARAM_MIN:
  454.     if (set)
  455.         asy_vmin(ifp->dev, val);
  456.     return ap->pktsize;
  457.     case PARAM_RTS:
  458.     if (set)
  459.         asy_rts(ifp->dev, val);
  460.     return (ap->flags & ASY_RTSCTS) == 0;
  461.     }
  462.     return -1;
  463. }
  464.  
  465. /*---------------------------------------------------------------------------*/
  466.  
  467. static void
  468. asy_input(dev, arg1, arg2)
  469.     int dev;
  470.     void *arg1, *arg2;
  471. {
  472.     struct timeval tv;
  473.     extern int errno;
  474.     struct asy *ap;
  475.     fd_set fds;
  476.     char *buf;
  477.     int i, c;
  478.  
  479.     ap = &Asy[dev];
  480.     for (;;)
  481.     {
  482.     if (pwait(&ap->fd) != 0)
  483.         return;
  484.     ap->rxints++;
  485.     buf = mallocw(ap->rxbuf);
  486.  
  487.     if (ap->pktsize)
  488.         fcntl(ap->fd, F_SETFL, fcntl(ap->fd, F_GETFL, 0) & ~O_NONBLOCK);
  489.     if ((i = read(ap->fd, buf, ap->rxbuf)) == 0 ||
  490.         (!ap->pktsize && i == -1 && errno == EWOULDBLOCK))
  491.     {
  492.         if (ap->pktsize)
  493.         fcntl(ap->fd, F_SETFL, fcntl(ap->fd, F_GETFL, 0) | O_NONBLOCK);
  494.         ap->rxblock++;
  495.         free(buf);
  496.         continue;
  497.     }
  498.     if (i == -1)
  499.     {
  500.         tprintf("asy_input(%d): read error %d, shutting down\n", dev,
  501.             errno);
  502.         if (ap->pktsize)
  503.         fcntl(ap->fd, F_SETFL, fcntl(ap->fd, F_GETFL, 0) | O_NONBLOCK);
  504.         free(buf);
  505.         return;
  506.     }
  507.     if ((c = ap->rxq) <= 0)
  508.         c = 1;
  509.     while (i > 0 && c > 0)
  510.     {
  511.         ap->rxchar += i;
  512.         ap->rxput++;
  513.         enqueue(&ap->rcvq, qdata(buf, i));
  514.         c--;
  515.         if (ap->pktsize)
  516.         {
  517.         /* can't just read to check for data, since it might block */
  518.         FD_ZERO(&fds);
  519.         FD_SET(ap->fd, &fds);
  520.         tv.tv_sec = tv.tv_usec = 0;
  521.         if (select(FD_SETSIZE, &fds, 0, 0, &tv) == 0)
  522.         {
  523.             i = -1;
  524.             errno = EWOULDBLOCK;
  525.             break;
  526.         }
  527.         }
  528.         i = read(ap->fd, buf, ap->rxbuf);
  529.     }
  530.     free(buf);
  531.     if (i == -1 && errno != EWOULDBLOCK)
  532.     {
  533.         tprintf("asy_input(%d): read error %d, shutting down\n", dev,
  534.             errno);
  535.         return;
  536.     }
  537.     if (ap->pktsize)
  538.         fcntl(ap->fd, F_SETFL, fcntl(ap->fd, F_GETFL, 0) | O_NONBLOCK);
  539.     if (c < 1 && ap->rxq > 1)
  540.         ap->rxovq++;
  541.     }
  542. }
  543.  
  544. int
  545. get_asy(dev)
  546. int dev;
  547. {
  548.     struct asy *ap;
  549.  
  550.     ap = &Asy[dev];
  551.     if (ap->iface == NULLIF)
  552.     return -1;
  553.     while (!ap->rcvq)
  554.     {
  555.     if (pwait(&ap->rcvq) != 0)
  556.         return -1;        /* may not be dead, e.g. alarm in dialer */
  557.     }
  558.     return PULLCHAR(&ap->rcvq);
  559. }
  560.  
  561. int
  562. doasystat(int argc,char **argv,void *p)
  563. {
  564.     register struct asy *asyp;
  565.     struct iface *ifp;
  566.     int i;
  567.  
  568.     if(argc < 2){
  569.         for(asyp = Asy;asyp < &Asy[ASY_MAX];asyp++){
  570.             if(asyp->iface != NULLIF)
  571.                 pasy(asyp);
  572.         }
  573.         return 0;
  574.     }
  575.     for(i=1;i<argc;i++){
  576.         if((ifp = if_lookup(argv[i])) == NULLIF){
  577.             tprintf("Interface %s unknown\n",argv[i]);
  578.             continue;
  579.         }
  580.         for(asyp = Asy;asyp < &Asy[ASY_MAX];asyp++){
  581.             if(asyp->iface == ifp){
  582.                 pasy(asyp);
  583.                 break;
  584.             }
  585.         }
  586.         if(asyp == &Asy[ASY_MAX])
  587.             tprintf("Interface %s not asy\n",argv[i]);
  588.     }
  589.  
  590.     return 0;
  591. }
  592.  
  593. /*---------------------------------------------------------------------------*/
  594.  
  595. static void
  596. pasy(asyp)
  597. struct asy *asyp;
  598. {
  599.     tprintf("%s: %lu bps, ", asyp->iface->name, asyp->speed);
  600.     if (asyp->pktsize)
  601.     tprintf("packet size %d", asyp->pktsize);
  602.     else
  603.     tprintf("non-blocking");
  604.     tprintf(", RTS/CTS %sabled", (asyp->flags & ASY_RTSCTS? "en": "dis"));
  605.     tprintf(", carrier %sabled\n", (asyp->flags & ASY_CARR? "en": "dis"));
  606.     tprintf("  RX: ints %lu chars %lu puts %lu buf %d rxqueue %d qlen %d ovq "
  607.         "%ld block %ld\n",
  608.         asyp->rxints, asyp->rxchar, asyp->rxput, asyp->rxbuf, asyp->rxq,
  609.         len_q(asyp->rcvq), asyp->rxovq, asyp->rxblock);
  610.     tprintf("  TX: ints %lu gets %lu chars %lu txqueue %d qlen %d ovq %ld "
  611.         "block %ld\n",
  612.         asyp->txints, asyp->txget, asyp->txchar, asyp->txq,
  613.         len_q(asyp->sndq), asyp->txovq, asyp->txblock);
  614. }
  615.  
  616. /*---------------------------------------------------------------------------*/
  617.  
  618. /* Serial transmit process, common to all protocols */
  619.  
  620. /*
  621.  * Yes, this badly needs to be rewritten.
  622.  */
  623.  
  624. static void
  625. asy_tx(dev, p1, p2)
  626.     int dev;
  627.     void *p1, *p2;
  628. {
  629.     register struct mbuf *bp;
  630.     struct asy *asyp;
  631.     int c, l, off;
  632.  
  633.     asyp = &Asy[dev];
  634.     if ((c = asyp->txq) <= 0)
  635.     c = 1;
  636.     for (;;)
  637.     {
  638.     while (asyp->sndq == NULLBUF)
  639.     {
  640.         if (!(c = asyp->txq))
  641.         c = 1;
  642.         if (pwait(&asyp->sndq) != 0)
  643.         return;
  644.         asyp->txints++;
  645.     }
  646.     bp = dequeue(&asyp->sndq);
  647.     asyp->txget++;
  648.     off = 0;
  649.     while (bp != NULLBUF)
  650.     {
  651.         l = write(asyp->fd, bp->data + off, (size_t)bp->cnt - off);
  652.         if (l == -1 && errno != EWOULDBLOCK)
  653.         {
  654.         tprintf("asy_tx(%d): write error %d, shutting down\n", dev,
  655.             errno);
  656.         return;
  657.         }
  658.         if (l == -1)
  659.         l = 0;
  660.         asyp->txchar += l;
  661.         if (l == bp->cnt - off)
  662.         {
  663.         bp = free_mbuf(bp);
  664.         off = 0;
  665.         }
  666.         else
  667.         {
  668.         asyp->txblock++;
  669.         pwait(NULL);
  670.         off += l;
  671.         }
  672.     }
  673.     if (--c < 1 && asyp->txq > 1)
  674.     {
  675.         asyp->txovq++;
  676.         pwait(NULL);
  677.     }
  678.     }
  679. }
  680.  
  681. /*---------------------------------------------------------------------------*/
  682.  
  683. /* Send a message on the specified serial line */
  684. int
  685. asy_send(dev,bp)
  686. int dev;
  687. struct mbuf *bp;
  688. {
  689.     struct asy *asyp;
  690.  
  691.     if(dev < 0 || dev >= ASY_MAX){
  692.         free_p(bp);
  693.         return -1;
  694.     }
  695.     asyp = &Asy[dev];
  696.  
  697.     if(asyp->iface == NULLIF)
  698.         free_p(bp);
  699.     else
  700.         enqueue(&asyp->sndq, bp);
  701.     return 0;
  702. }
  703.  
  704. /* stub, CD not enabled at present */
  705.  
  706. int
  707. carrier_detect(dev)
  708.     int dev;
  709. {
  710.     return 1;            /* assume always on, with CLOCAL it is! */
  711. }
  712.  
  713. /*---------------------------------------------------------------------------*/
  714.  
  715. int
  716. doasyconfig(ac, av, p)
  717.     int ac;
  718.     char **av;
  719.     void *p;
  720. {
  721.     struct iface *ip;
  722.     struct asy *ap;
  723.  
  724.     if (ac < 3)
  725.     return 1;
  726.     if (!(ip = if_lookup(av[1])))
  727.     {
  728.     tprintf("Interface %s unknown\n", av[1]);
  729.     return 1;
  730.     }
  731.     for (ap = Asy; ap < &Asy[ASY_MAX]; ap++)
  732.     {
  733.     if (ap->iface == ip)
  734.         break;
  735.     }
  736.     if (!ap)
  737.     {
  738.     tprintf("Interface %s not asy\n", av[1]);
  739.     return 1;
  740.     }
  741.     return subcmd(AsyPcmds, ac - 1, av + 1, ap);
  742. }
  743.  
  744. static int
  745. doasy2stat(ac, av, d)
  746.     int ac;
  747.     char **av;
  748.     void *d;
  749. {
  750.     pasy((struct asy *) d);
  751.     return 0;
  752. }
  753.  
  754. static int
  755. dorxqueue(ac, av, d)
  756.     int ac;
  757.     char **av;
  758.     void *d;
  759. {
  760.     return setint(&((struct asy *) d)->rxq, "Receive queue size", ac, av);
  761. }
  762.  
  763. static int
  764. dotxqueue(ac, av, d)
  765.     int ac;
  766.     char **av;
  767.     void *d;
  768. {
  769.     return setint(&((struct asy *) d)->txq, "Transmit queue size", ac, av);
  770. }
  771.  
  772. static int
  773. dobufsize(ac, av, d)
  774.     int ac;
  775.     char **av;
  776.     void *d;
  777. {
  778.     return setuns(&((struct asy *) d)->rxbuf, "Receive buffer size", ac, av);
  779. }
  780.